<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.9.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"mjava.top","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":true},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="浅水是喧哗的，深水是沉默的">
<meta name="keywords" content="Java,Linux,Spring,Jenkins,Docker,RocketMQ,Vue">
<meta property="og:type" content="website">
<meta property="og:title" content="灰色World">
<meta property="og:url" content="http://mjava.top/index.html">
<meta property="og:site_name" content="灰色World">
<meta property="og:description" content="浅水是喧哗的，深水是沉默的">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="灰色World">
<meta name="twitter:description" content="浅水是喧哗的，深水是沉默的">

<link rel="canonical" href="http://mjava.top/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>灰色World</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="灰色World" type="application/atom+xml"><!-- hexo-inject:begin --><!-- hexo-inject:end -->
<link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>

<body itemscope itemtype="http://schema.org/WebPage">
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">灰色World</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/greycode9" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener external nofollow noreferrer" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/linux/79b5fe12-9c60-4b93-be92-dffb00fa39c7/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/linux/79b5fe12-9c60-4b93-be92-dffb00fa39c7/" class="post-title-link" itemprop="url">Hexo使用UUID生成文章路径</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2021-01-27 17:51:05 / 修改时间：10:07:24" itemprop="dateCreated datePublished" datetime="2021-01-27T17:51:05+00:00">2021-01-27</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Linux/" itemprop="url" rel="index"><span itemprop="name">Linux</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="教程"><a href="#教程" class="headerlink" title="教程"></a>教程</h2><ol>
<li>编写一个名为<strong>hexoN</strong>的脚本文件</li>
</ol>
<figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line">uuid=$(sudo cat /proc/sys/kernel/random/uuid)</span><br><span class="line">echo $uuid</span><br><span class="line">hexo new $uuid</span><br></pre></td></tr></table></figure>

<ol start="2">
<li>添加执行权限</li>
</ol>
<figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">chmod +x hexoN</span><br></pre></td></tr></table></figure>

<ol start="3">
<li>在用户根目录的<code>.zshrc</code>(因为我用的是ohmyzsh，所以是这个文件，一般是<code>.bashrc</code>，也可直接加载系统文件<code>/etc/profile</code>中)追加一条</li>
</ol>
<figure class="highlight shell"><table><tr><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 后面地址是存放这个脚本的文件夹路径 根据实际更改</span></span><br><span class="line">export PATH=$PATH:/home/zheng/software/shell</span><br></pre></td></tr></table></figure>

<ol start="4">
<li>执行命令是刚才追加的内容生效</li>
</ol>
<figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">source .zshrc</span><br></pre></td></tr></table></figure>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/linux/79b5fe12-9c60-4b93-be92-dffb00fa39c7/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/linux/github-actions-build-pi-kernerl/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/linux/github-actions-build-pi-kernerl/" class="post-title-link" itemprop="url">使用GitHub Actions编译树莓派内核</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-26 15:56:07" itemprop="dateCreated datePublished" datetime="2021-01-26T15:56:07+00:00">2021-01-26</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Linux/" itemprop="url" rel="index"><span itemprop="name">Linux</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="仓库地址"><a href="#仓库地址" class="headerlink" title="仓库地址"></a>仓库地址</h2><p>仓库地址：<a href="https://github.com/GreyCode9/make-raspberrypi-kernel" rel="noopener external nofollow noreferrer" target="_blank">https://github.com/GreyCode9/make-raspberrypi-kernel</a></p>
<h2 id="创建秘钥"><a href="#创建秘钥" class="headerlink" title="创建秘钥"></a>创建秘钥</h2><ol>
<li>点击Github右上角头像 -&gt; Settings -&gt; Developer settings -&gt; Personal access tokens -&gt; Generate new token</li>
</ol>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/linux/github-actions-build-pi-kernerl/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/recommend/git-commend-note/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/recommend/git-commend-note/" class="post-title-link" itemprop="url">Git常用命令</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:16:56" itemprop="dateCreated datePublished" datetime="2020-09-16T15:16:56+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Git简介"><a href="#Git简介" class="headerlink" title="Git简介"></a>Git简介</h2><p>Git 是用于 Linux<a href="https://baike.baidu.com/item/内核" rel="noopener external nofollow noreferrer" target="_blank">内核</a>开发的<a href="https://baike.baidu.com/item/版本控制" rel="noopener external nofollow noreferrer" target="_blank">版本控制</a>工具。与常用的版本控制工具 CVS, Subversion 等不同，它采用了分布式版本库的方式，不必服务器端软件支持（wingeddevil注：这得分是用什么样的服务端，使用http协议或者git协议等不太一样。并且在push和pull的时候和服务器端还是有交互的。），使<a href="https://baike.baidu.com/item/源代码" rel="noopener external nofollow noreferrer" target="_blank">源代码</a>的发布和交流极其方便。 Git 的速度很快，这对于诸如 Linux kernel 这样的大项目来说自然很重要。 Git 最为出色的是它的合并跟踪（merge tracing）能力。</p>
<p>git对于很多人来说,真的是又爱又恨,用的好可以提示开发效率;用不好,解决各种冲突就要累的你半死</p>
<h2 id="git结构"><a href="#git结构" class="headerlink" title="git结构"></a>git结构</h2><blockquote>
<p>网上有 我就不画了</p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200605001853.png" alt="git结构图"></p>
<ul>
<li><p>workspace    相当于就是我们的本地电脑上的文件</p>
</li>
<li><p>Index    缓存区</p>
</li>
<li><p>Repository    本地仓库</p>
</li>
<li><p>Remote    远程仓库(github/gitlab/gitee)</p>
</li>
</ul>
<h2 id="git命令"><a href="#git命令" class="headerlink" title="git命令"></a>git命令</h2><p>git官方提供的命令多达几百个,可是我们日常却用不到这么多</p>
<p>所以我就整理了一下日常使用的命令</p>
<p>现在关注微信公招:<code>灰色Code</code></p>
<p>回复关键字:<code>git</code></p>
<p>就可以获取思维导图高清图片及导图源地址</p>
<p><img src="http://cdn.mjava.top/blog/20200605002904.jpg" alt></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/spring/fegin-resttemplate-addheard/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/spring/fegin-resttemplate-addheard/" class="post-title-link" itemprop="url">Fegin和RestTemplate添加全局请求头</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:14:43" itemprop="dateCreated datePublished" datetime="2020-09-16T15:14:43+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Spring/" itemprop="url" rel="index"><span itemprop="name">Spring</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Fegin添加全局请求头"><a href="#Fegin添加全局请求头" class="headerlink" title="Fegin添加全局请求头"></a>Fegin添加全局请求头</h2><ul>
<li>实现RequestInterceptor接口</li>
</ul>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 实现RequestInterceptor接口的apply方法</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FeignRequestInterceptor</span> <span class="keyword">implements</span> <span class="title">RequestInterceptor</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">apply</span><span class="params">(RequestTemplate requestTemplate)</span> </span>&#123;</span><br><span class="line">        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder</span><br><span class="line">                .getRequestAttributes();</span><br><span class="line">        HttpServletRequest request = attributes.getRequest();</span><br><span class="line">        Enumeration&lt;String&gt; headerNames = request.getHeaderNames();</span><br><span class="line">        <span class="keyword">if</span> (headerNames != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">while</span> (headerNames.hasMoreElements()) &#123;</span><br><span class="line">                String name = headerNames.nextElement();</span><br><span class="line">                String values = request.getHeader(name);</span><br><span class="line">                requestTemplate.header(name, values);</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>在<code>@FeginClient</code>注释里<code>configuration</code>所填入的类文件中添加上面的拦截器</p>
<blockquote>
<p>比如 </p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line">&gt; <span class="comment">// configuration指定的类为FeignConfig</span></span><br><span class="line">&gt; </span><br><span class="line">&gt; <span class="meta">@FeignClient</span>(name = <span class="string">"$&#123;TinyConfigServiceName&#125;"</span>,path=<span class="string">"/config"</span>,configuration = FeignConfig.class)</span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure>
</blockquote>
<ul>
<li><p>在FeignConfig类中添加拦截器</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FeignConfig</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> RequestInterceptor <span class="title">requestInterceptor</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> FeignRequestInterceptor();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



</li>
</ul>
</li>
</ul>
<h2 id="RestTemplate添加全局请求头"><a href="#RestTemplate添加全局请求头" class="headerlink" title="RestTemplate添加全局请求头"></a>RestTemplate添加全局请求头</h2><ul>
<li><p>编写拦截器,实现<code>ClientHttpRequestInterceptor</code>接口的<code>intercept</code>方法</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyInterceptor</span> <span class="keyword">implements</span> <span class="title">ClientHttpRequestInterceptor</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ClientHttpResponse <span class="title">intercept</span><span class="params">(HttpRequest httpRequest, <span class="keyword">byte</span>[] bytes, ClientHttpRequestExecution clientHttpRequestExecution)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        HttpHeaders httpHeaders=httpRequest.getHeaders();</span><br><span class="line">        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder</span><br><span class="line">                .getRequestAttributes();</span><br><span class="line">        HttpServletRequest request = attributes.getRequest();</span><br><span class="line">        Enumeration&lt;String&gt; headerNames = request.getHeaderNames();</span><br><span class="line">        <span class="keyword">if</span> (headerNames != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">while</span> (headerNames.hasMoreElements()) &#123;</span><br><span class="line">                String name = headerNames.nextElement();</span><br><span class="line">                String values = request.getHeader(name);</span><br><span class="line">                httpHeaders.add(name, values);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> clientHttpRequestExecution.execute(httpRequest,bytes);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



</li>
</ul>
<ul>
<li><p>在springboot的启动类里添加<code>RestTemplate</code></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DemoApplication</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SpringApplication.run(DemoApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//ioc添加RestTemplate</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> RestTemplate <span class="title">restTemplate</span><span class="params">()</span></span>&#123;</span><br><span class="line">        MyInterceptor myInterceptor=<span class="keyword">new</span> MyInterceptor();</span><br><span class="line">        RestTemplate restTemplate=<span class="keyword">new</span> RestTemplate();</span><br><span class="line">        restTemplate.setInterceptors(Collections.singletonList(myInterceptor));</span><br><span class="line">        <span class="keyword">return</span> restTemplate;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/mdc-test/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/mdc-test/" class="post-title-link" itemprop="url">浅谈MDC</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:10:47" itemprop="dateCreated datePublished" datetime="2020-09-16T15:10:47+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="MDC是什么？"><a href="#MDC是什么？" class="headerlink" title="MDC是什么？"></a>MDC是什么？</h2><p><code>MDC</code> 全拼 <code>Mapped Diagnostic Contexts</code>，是<code>SLF4J</code>类日志系统中实现分布式多线程日志数据传递的重要工具；可利用<code>MDC</code>将一些运行时的上下文数据打印出来。目前只有<code>log4j</code>和<code>logback</code>提供原生的<code>MDC</code>支持；</p>
<h2 id="简单使用"><a href="#简单使用" class="headerlink" title="简单使用"></a>简单使用</h2><p><code>MDC</code>里面提供的都是静态方法，所以可以直接调用</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 设置一个key</span></span><br><span class="line">MDC.put(<span class="string">"name"</span>,<span class="string">"灰色Code"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取一个key的值</span></span><br><span class="line">MDC.get(<span class="string">"name"</span>);</span><br><span class="line">    </span><br><span class="line"><span class="comment">// 删除一个key</span></span><br><span class="line">MDC.remove(<span class="string">"name"</span>);</span><br><span class="line">    </span><br><span class="line"><span class="comment">// 清空MDC里的内容</span></span><br><span class="line">MDC.clear();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取上下文中的map</span></span><br><span class="line">Map&lt;String,String&gt; map = MDC.getCopyOfContextMap();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 设置MDC的map</span></span><br><span class="line">MDC.setContextMap(map);</span><br></pre></td></tr></table></figure>

<h2 id="源码解析"><a href="#源码解析" class="headerlink" title="源码解析"></a>源码解析</h2><h3 id="MDC"><a href="#MDC" class="headerlink" title="MDC"></a>MDC</h3><p>通过阅读<code>MDC</code>的源码可以发现，它其实是调用了<code>MDCAdapter</code>的接口来实现的</p>
<p><img src="http://cdn.mjava.top/blog/20200729200214.png" alt></p>
<h3 id="MDCAdapter"><a href="#MDCAdapter" class="headerlink" title="MDCAdapter"></a>MDCAdapter</h3><p><code>MDCAdapter</code>接口有三个实现类，而<code>MDC</code>是调用了<code>LogbackMDCAdapter</code>里的方法(在MDC里有一个静态代码块，实例化了这个对象)</p>
<p><img src="http://cdn.mjava.top/blog/20200729201118.png" alt></p>
<h3 id="LogbackMDCAdapter"><a href="#LogbackMDCAdapter" class="headerlink" title="LogbackMDCAdapter"></a>LogbackMDCAdapter</h3><p><strong>而</strong><code>LogbackMDCAdapter</code>主要是用<code>ThreadLocal</code>在线程上下文中维护一个<code>HashMap</code>来实现的</p>
<p><img src="http://cdn.mjava.top/blog/20200729201650.png" alt></p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>怎么样,实现原理是不是很简单，就这么短短几行代码，就实现了听起来很高大上的<code>MDC</code>。</p>
<p>所以简单来说，<code>MDC</code>就是利用<code>ThreadLocal</code>在线程中维护了一个<code>HashMap</code>，利用<code>HashMap</code>来存放数据</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jdkproxy-cglib/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jdkproxy-cglib/" class="post-title-link" itemprop="url">JDKproxy和Cglib初探</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:09:47" itemprop="dateCreated datePublished" datetime="2020-09-16T15:09:47+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="JDKproxy和Cglib初探"><a href="#JDKproxy和Cglib初探" class="headerlink" title="JDKproxy和Cglib初探"></a>JDKproxy和Cglib初探</h1><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>在Java中，动态代理机制的出现，使得Java开发人员不用手工编写代理类，只要简单地制定一组接口及委托类对象，便能动态地获得代理类。动态代理在Java中有着广泛的应用，比如Spring AOP，Hibernate数据查询、测试框架的后端mock、RPC，Java注解对象获取等。</p>
<h2 id="JDK原生动态代理-JDKProxy"><a href="#JDK原生动态代理-JDKProxy" class="headerlink" title="JDK原生动态代理(JDKProxy)"></a>JDK原生动态代理(JDKProxy)</h2><p><code>JDKProxy</code>只能对<code>实现了接口的类</code>生成代理，而不能针对<code>普通类</code> 。<code>JDKProxy</code>原生的<code>反射API</code>进行操作，在生成类上比较高效。</p>
<h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><p><a href="http://cdn.mjava.top/blog/20200729000830.png" rel="noopener external nofollow noreferrer" target="_blank"></a></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">TestInterface</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">test</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestClass</span> <span class="keyword">implements</span> <span class="title">TestInterface</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"JDK动态代理"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//主方法</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JDKProxy</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        TestClass testClass=<span class="keyword">new</span> TestClass();</span><br><span class="line">        ProxyHandle proxyHandle=<span class="keyword">new</span> ProxyHandle(testClass);</span><br><span class="line">        <span class="comment">//使用接口</span></span><br><span class="line">        TestInterface testClass1= (TestInterface) Proxy.newProxyInstance(</span><br><span class="line">                testClass.getClass().getClassLoader(),</span><br><span class="line">                testClass.getClass().getInterfaces(),proxyHandle);</span><br><span class="line">        testClass1.test();</span><br><span class="line">        System.out.println(<span class="string">"代理类名称："</span>+testClass1.getClass());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//代理</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ProxyHandle</span> <span class="keyword">implements</span> <span class="title">InvocationHandler</span></span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Object originaObj;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">ProxyHandle</span><span class="params">(Object o)</span></span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.originaObj=o;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"前置"</span>);</span><br><span class="line">        Object object=method.invoke(originaObj,args);</span><br><span class="line">        System.out.println(<span class="string">"后置"</span>);</span><br><span class="line">        <span class="keyword">return</span> object;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">输出结果：</span><br><span class="line">	前置</span><br><span class="line">    JDK动态代理</span><br><span class="line">    后置</span><br><span class="line">    代理类名称：class com.example.demo.aop.$Proxy0</span><br></pre></td></tr></table></figure>

<h2 id="Cglib"><a href="#Cglib" class="headerlink" title="Cglib"></a>Cglib</h2><p><code>Cglib</code>代理是针对<code>所有类</code>（包括实现接口的类和普通的类）实现代理，主要是对指定的类<strong>生成一个子类</strong>，覆盖其中的方法(<strong>所以该类或方法不能声明称final的</strong>) 。<code>Cglib</code>使用<code>ASM框架</code>直接对字节码进行操作，在类的执行过程中比较高效</p>
<h3 id="使用-1"><a href="#使用-1" class="headerlink" title="使用"></a>使用</h3><p><a href="http://cdn.mjava.top/blog/20200729001250.png" rel="noopener external nofollow noreferrer" target="_blank"></a></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">InterTest</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">t1</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">InterClass</span> <span class="keyword">implements</span> <span class="title">InterTest</span></span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">t1</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"我是接口测试方法"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CglibTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 普通类</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line">        Enhancer enhancer=<span class="keyword">new</span> Enhancer();</span><br><span class="line">        enhancer.setSuperclass(CG.class);</span><br><span class="line">        enhancer.setCallback(<span class="keyword">new</span> MethodInterceptor() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> Object <span class="title">intercept</span><span class="params">(Object o, Method method,</span></span></span><br><span class="line"><span class="function"><span class="params">                                    Object[] objects,</span></span></span><br><span class="line"><span class="function"><span class="params">                                    MethodProxy methodProxy)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">                System.out.println(<span class="string">"前置"</span>);</span><br><span class="line">                Object object=methodProxy.invokeSuper(o,objects);</span><br><span class="line">                System.out.println(<span class="string">"后置"</span>);</span><br><span class="line">                <span class="keyword">return</span> object;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        CG cglibTest= (CG) enhancer.create();</span><br><span class="line">        cglibTest.test();</span><br><span class="line">        System.out.println(<span class="string">"代理类名称1："</span>+cglibTest.getClass());</span><br><span class="line"></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">         * 实现了接口的类</span></span><br><span class="line"><span class="comment">         * */</span></span><br><span class="line">        Enhancer enhancer2=<span class="keyword">new</span> Enhancer();</span><br><span class="line">        enhancer2.setSuperclass(InterClass.class);</span><br><span class="line">        enhancer2.setCallback(<span class="keyword">new</span> MethodInterceptor() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> Object <span class="title">intercept</span><span class="params">(Object o, Method method,</span></span></span><br><span class="line"><span class="function"><span class="params">                                    Object[] objects,</span></span></span><br><span class="line"><span class="function"><span class="params">                                    MethodProxy methodProxy)</span> <span class="keyword">throws</span> Throwable </span>&#123;</span><br><span class="line">                System.out.println(<span class="string">"接口类前置"</span>);</span><br><span class="line">                Object object=methodProxy.invokeSuper(o,objects);</span><br><span class="line">                System.out.println(<span class="string">"接口类后置"</span>);</span><br><span class="line">                <span class="keyword">return</span> object;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        InterClass interClass= (InterClass) enhancer2.create();</span><br><span class="line">        interClass.t1();</span><br><span class="line">        System.out.println(<span class="string">"代理类名称2："</span>+interClass.getClass());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CG</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"代理类测试"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">输出结果：</span><br><span class="line">	前置</span><br><span class="line">    代理类测试</span><br><span class="line">    后置</span><br><span class="line">    代理类名称1：class com.example.demo.aop.CG$$EnhancerByCGLIB$$5c6cbf31</span><br><span class="line">    </span><br><span class="line">    接口类前置</span><br><span class="line">    我是接口测试方法</span><br><span class="line">    接口类后置</span><br><span class="line">    代理类名称2：class com.example.demo.aop.InterClass$$EnhancerByCGLIB$$80c75859</span><br></pre></td></tr></table></figure>
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/java-base-data-pack/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/java-base-data-pack/" class="post-title-link" itemprop="url">Java包装类缓存机制</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:08:18" itemprop="dateCreated datePublished" datetime="2020-09-16T15:08:18+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="面试题"><a href="#面试题" class="headerlink" title="面试题"></a>面试题</h2><p>首先,来看一道常见的面试题,下面代码运行后会输出什么?</p>
<p><img src="http://cdn.mjava.top/blog/20200603110911.png" alt></p>
<p>上面代码运行后,最终会输出<code>false</code>和<code>true</code>;为什么会这样呢?</p>
<p>按道理来说,在Java中<code>==</code>是比较两个对象的地址,上面代码中<code>i3</code>和<code>i4</code>是两个不同的对象,理应也应该返回是<code>false</code>,怎么返回是<code>true</code>呢?让我们慢慢往下看</p>
<h2 id="Integer的缓存机制"><a href="#Integer的缓存机制" class="headerlink" title="Integer的缓存机制"></a>Integer的缓存机制</h2><p>让我们来看看他的源代码.</p>
<p>当执行<code>Integer i=128;</code>这个语句时,Java会调用<code>valueOf(int i)</code>方法,然后<code>自动装箱</code>的方式,让其变成<code>Integer i=new Integer(128)</code>,具体源码如下:</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Integer <span class="title">valueOf</span><span class="params">(<span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (i &gt;= IntegerCache.low &amp;&amp; i &lt;= IntegerCache.high)</span><br><span class="line">        <span class="keyword">return</span> IntegerCache.cache[i + (-IntegerCache.low)];</span><br><span class="line">    <span class="comment">//装箱</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Integer(i);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>从上面的源码中可以看到,在装箱之前会执行一个<code>if</code>语句,这个<code>if</code>语句就是判断传入的值是否在缓存内,如果在缓存内,就直接返回缓存内的值,如果不在缓存内,就装箱,在堆内创建一个新空间来存放.</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">//Integer包装类缓存源码</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">IntegerCache</span> </span>&#123;</span><br><span class="line">        <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> low = -<span class="number">128</span>;</span><br><span class="line">        <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> high;</span><br><span class="line">        <span class="keyword">static</span> <span class="keyword">final</span> Integer cache[];</span><br><span class="line">        <span class="keyword">static</span> &#123;</span><br><span class="line">            <span class="comment">// high value may be configured by property</span></span><br><span class="line">            <span class="keyword">int</span> h = <span class="number">127</span>;</span><br><span class="line">            String integerCacheHighPropValue =</span><br><span class="line">                sun.misc.VM.getSavedProperty(<span class="string">"java.lang.Integer.IntegerCache.high"</span>);</span><br><span class="line">            <span class="keyword">if</span> (integerCacheHighPropValue != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="keyword">int</span> i = parseInt(integerCacheHighPropValue);</span><br><span class="line">                    i = Math.max(i, <span class="number">127</span>);</span><br><span class="line">                    <span class="comment">// Maximum array size is Integer.MAX_VALUE</span></span><br><span class="line">                    h = Math.min(i, Integer.MAX_VALUE - (-low) -<span class="number">1</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span>( NumberFormatException nfe) &#123;</span><br><span class="line">                    <span class="comment">// If the property cannot be parsed into an int, ignore it.</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            high = h;</span><br><span class="line">            cache = <span class="keyword">new</span> Integer[(high - low) + <span class="number">1</span>];</span><br><span class="line">            <span class="keyword">int</span> j = low;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">int</span> k = <span class="number">0</span>; k &lt; cache.length; k++)</span><br><span class="line">                cache[k] = <span class="keyword">new</span> Integer(j++);</span><br><span class="line">            <span class="comment">// range [-128, 127] must be interned (JLS7 5.1.7)</span></span><br><span class="line">            <span class="keyword">assert</span> IntegerCache.high &gt;= <span class="number">127</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> <span class="title">IntegerCache</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<p>从源码中可以看到,<code>Integer</code>的缓存范围是<code>-128~127</code>,所以过程大致如下:</p>
<p><img src="http://cdn.mjava.top/blog/20200603114246.png" alt></p>
<p>按照上面这个方法,只要在数据在缓存池范围内的,都会引用缓存在堆内的地址,所有上面的<code>i3==i4</code>会输出为<code>true</code>;而不在缓存范围内的,就会在堆中开放新的空间来存放对象,所以地址不同,用<code>==</code>比较返回也不同;</p>
<h2 id="其他包装类缓存机制"><a href="#其他包装类缓存机制" class="headerlink" title="其他包装类缓存机制"></a>其他包装类缓存机制</h2><p>除了<code>Integer</code>之外,其他的包装类也使用了缓存技术;</p>
<h3 id="Long"><a href="#Long" class="headerlink" title="Long"></a>Long</h3><blockquote>
<p>缓存范围-128~127</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Long <span class="title">valueOf</span><span class="params">(<span class="keyword">long</span> l)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">int</span> offset = <span class="number">128</span>;</span><br><span class="line">    <span class="keyword">if</span> (l &gt;= -<span class="number">128</span> &amp;&amp; l &lt;= <span class="number">127</span>) &#123; <span class="comment">// will cache</span></span><br><span class="line">        <span class="keyword">return</span> LongCache.cache[(<span class="keyword">int</span>)l + offset];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Long(l);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">LongCache</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">LongCache</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> Long cache[] = <span class="keyword">new</span> Long[-(-<span class="number">128</span>) + <span class="number">127</span> + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; cache.length; i++)</span><br><span class="line">            cache[i] = <span class="keyword">new</span> Long(i - <span class="number">128</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Byte"><a href="#Byte" class="headerlink" title="Byte"></a>Byte</h3><blockquote>
<p>缓存范围-128<del>127   (byte范围:一个byte占8位,所以取值范围是**-2^7</del>2^7-1**)</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Byte <span class="title">valueOf</span><span class="params">(<span class="keyword">byte</span> b)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">int</span> offset = <span class="number">128</span>;</span><br><span class="line">    <span class="keyword">return</span> ByteCache.cache[(<span class="keyword">int</span>)b + offset];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ByteCache</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">ByteCache</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> Byte cache[] = <span class="keyword">new</span> Byte[-(-<span class="number">128</span>) + <span class="number">127</span> + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; cache.length; i++)</span><br><span class="line">            cache[i] = <span class="keyword">new</span> Byte((<span class="keyword">byte</span>)(i - <span class="number">128</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Character"><a href="#Character" class="headerlink" title="Character"></a>Character</h3><blockquote>
<p>缓存范围0~127  (ascii码范围) </p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Character <span class="title">valueOf</span><span class="params">(<span class="keyword">char</span> c)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (c &lt;= <span class="number">127</span>) &#123; <span class="comment">// must cache</span></span><br><span class="line">        <span class="keyword">return</span> CharacterCache.cache[(<span class="keyword">int</span>)c];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Character(c);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">CharacterCache</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">CharacterCache</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> Character cache[] = <span class="keyword">new</span> Character[<span class="number">127</span> + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; cache.length; i++)</span><br><span class="line">            cache[i] = <span class="keyword">new</span> Character((<span class="keyword">char</span>)i);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Short"><a href="#Short" class="headerlink" title="Short"></a>Short</h3><blockquote>
<p>缓存范围-128~127</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Short <span class="title">valueOf</span><span class="params">(<span class="keyword">short</span> s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">int</span> offset = <span class="number">128</span>;</span><br><span class="line">    <span class="keyword">int</span> sAsInt = s;</span><br><span class="line">    <span class="keyword">if</span> (sAsInt &gt;= -<span class="number">128</span> &amp;&amp; sAsInt &lt;= <span class="number">127</span>) &#123; <span class="comment">// must cache</span></span><br><span class="line">        <span class="keyword">return</span> ShortCache.cache[sAsInt + offset];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Short(s);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ShortCache</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">ShortCache</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> Short cache[] = <span class="keyword">new</span> Short[-(-<span class="number">128</span>) + <span class="number">127</span> + <span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; cache.length; i++)</span><br><span class="line">            cache[i] = <span class="keyword">new</span> Short((<span class="keyword">short</span>)(i - <span class="number">128</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Boolean"><a href="#Boolean" class="headerlink" title="Boolean"></a>Boolean</h3><blockquote>
<p>缓存范围 <code>true</code>  <code>false</code>     它只设置了两个静态变量用来充当缓存</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Boolean TRUE = <span class="keyword">new</span> Boolean(<span class="keyword">true</span>);</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Boolean FALSE = <span class="keyword">new</span> Boolean(<span class="keyword">false</span>);</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Boolean <span class="title">valueOf</span><span class="params">(<span class="keyword">boolean</span> b)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (b ? TRUE : FALSE);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="建议"><a href="#建议" class="headerlink" title="建议"></a>建议</h2><p>包装类对比数据是否相同的时候,建议采用重写的<code>equals()</code>方法.</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/java-jvm-stack-1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/java-jvm-stack-1/" class="post-title-link" itemprop="url">JVM运行时栈帧</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:06:15" itemprop="dateCreated datePublished" datetime="2020-09-16T15:06:15+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>在JVM中，每个线程都包含n个栈帧，每一个栈帧都包括了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。</p>
<p>栈帧的生命周期<strong>随着方法的创建而创建，随着方法的结束而销毁，无论方法是正常完成还是异常完成（抛出了在方法内未被捕获的异常）都算方法的结束。</strong></p>
<p>在某条线程执行过程中的某个时间点上，只有目前正在执行的那个方法的栈帧是活动的。这个栈帧称为<strong>当前栈帧</strong>，这个栈帧对应的方法称为<strong>当前方法</strong>，定义这个方法的类称为<strong>当前类</strong>。<strong>对局部变量表和操作数栈的各种操作，通常都指的是对当前栈帧的局部变量表和操作数栈所进行的操作。</strong></p>
<blockquote>
<p><strong>注意:</strong>栈帧是线程本地私有的数据，不可能在一个栈帧 之中引用另外一个线程的栈帧</p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200731162235.jpg" alt></p>
<h2 id="局部变量表"><a href="#局部变量表" class="headerlink" title="局部变量表"></a>局部变量表</h2><p><code>局部变量表（Local Variables Table）</code>是一组<strong>变量值</strong>的存储空间，用于存放<strong>方法参数</strong>和<strong>方法内部定义的局部变量</strong>。</p>
<h3 id="存储方法"><a href="#存储方法" class="headerlink" title="存储方法"></a>存储方法</h3><p>局部变量表的容量以<code>变量槽（Variable Slot）</code>为最小单位，一般在虚拟机中，一个Slot占用<strong>32位</strong>存储空间(这不是固定的，虚拟机可以自行改变每个槽占用空间的大小,但一般都是32位)。</p>
<p>Java虚拟机通过<strong>索引定位</strong>的方式使用局部变量表，索引值的范围是从<code>0</code>开始至局部变量表最大的变量槽数量。如果访问的是32位数据类型的变量，索引N就代表了使用第N个变量槽，如果访问的是64位数据类型的变量，则说明会同时使用第N和N+1两个变量槽。</p>
<h4 id="eg"><a href="#eg" class="headerlink" title="eg:"></a>eg:</h4><p>在Java中，<code>long</code>在内存占64位，所以局部变量表<strong>用2个slot来存储</strong></p>
<p><img src="http://cdn.mjava.top/blog/20200730225516.png" alt></p>
<p>对于两个相邻的共同存放一个64位数据的两个变量槽，虚拟机<strong>不允许采用任何方式单独访问其中的某一个</strong>，《Java虚拟机规范》中明确要求了如果遇到进行这种操作的字节码序列，虚拟机就应该在类加载的校验阶段中抛出异常。</p>
<h3 id="long和double的非原子性协定"><a href="#long和double的非原子性协定" class="headerlink" title="long和double的非原子性协定"></a>long和double的非原子性协定</h3><blockquote>
<p>在Java内存模型中，对于64位的数据类型（long和double），在模型中特别定义了一条宽松的规定：<strong>允许虚拟机将没有被volatile修饰的64位数据的读写操作划分为两次32位的操作来进行</strong>，即允许虚拟机实现自行选择是否要保证64位数据类型的load、store、read和write这四个操作的原子性，这就是所谓的<strong>“long和double的非原子性协定”（Non-Atomic Treatment of doubleand long Variables）</strong>。</p>
</blockquote>
<p>虽然有这个协定，<strong>但是</strong>，由于<code>局部变量表(Local Variable Table)</code>是建立在线程堆栈中的，属于<strong>线程私有的数据</strong>，无论读写两个连续的变量槽是否为原子操作，都<strong>不会引起数据竞争和线程安全问题</strong>。</p>
<h3 id="初始值问题"><a href="#初始值问题" class="headerlink" title="初始值问题"></a>初始值问题</h3><p>我们已经知道<strong>类的字段变量</strong>有两次赋初始值的过程，一次在<strong>准备阶段</strong>，赋予系统初始值；另外一次在<strong>初始化阶段</strong>，赋予程序员定义的初始值。</p>
<p>但<strong>局部变量就不一样</strong>了，如果一个局部变量定义了但<strong>没有赋初始值</strong>，那它是<strong>完全不能使用</strong>的。所以不要认为Java中任何情况下都存在诸如整型变量默认为0、布尔型变量默认为false等这样的默认值规则。</p>
<h4 id="eg："><a href="#eg：" class="headerlink" title="eg："></a>eg：</h4><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 这个方法会报：</span></span><br><span class="line"><span class="comment">// Error:(12, 28) java: variable y might not have been initialized</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JVMTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> y;</span><br><span class="line">        <span class="keyword">int</span> z=<span class="number">3</span>;</span><br><span class="line">        System.out.println(y+z);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这个会正常输出 3； 因为int的初始值为0</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JVMTest</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> y;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> z=<span class="number">3</span>;</span><br><span class="line">        System.out.println(y+z);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="操作数栈"><a href="#操作数栈" class="headerlink" title="操作数栈"></a>操作数栈</h2><p><code>操作数栈（Operand Stack）</code>也常被称为<code>操作栈</code>，它是一个后入先出（Last In First Out，LIFO）栈。同局部变量表一样，操作数栈的最大深度也在编译的时候被写入到Code属性的<code>max_stacks</code>数据项之中。操作数栈的每一个元素都可以是包括long和double在内的任意Java数据类型。32位数据类型所占的栈容量为1，64位数据类型所占的栈容量为2。Javac编译器的数据流分析工作保证了在方法执行的任何时候，操作数栈的深度都不会超过在<code>max_stacks</code>数据项中设定的最大值。</p>
<h3 id="eg-1"><a href="#eg-1" class="headerlink" title="eg:"></a>eg:</h3><figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JVMTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">long</span> y=<span class="number">9223372036854775800L</span>;</span><br><span class="line">        <span class="keyword">int</span> z=<span class="number">2</span>;</span><br><span class="line">        <span class="keyword">long</span> x=y+z;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>我们用<code>javap -verbose JVMTest</code>来查看他的<code>class</code>文件的字节码指令</p>
<p><img src="http://cdn.mjava.top/blog/20200730235131.png" alt></p>
<p><strong>在操作栈中的流程大致为：</strong></p>
<p><img src="http://cdn.mjava.top/blog/20200731105247.jpg" alt></p>
<h2 id="动态链接"><a href="#动态链接" class="headerlink" title="动态链接"></a>动态链接</h2><p>每个栈帧都包含一个指向当前方法所在类型的<code>运行时常量池</code>的引用，持有这个引用是为了支持<code>方法调用</code>过程中的<code>动态连接（Dynamic Linking）</code>。在<code>Class</code>文件里，一个方法若要调用其他方法，或者访问成员变量，则需要通过<code>符号引用(symolic reference)</code>来表示，<code>动态链接</code>的作用就是将这些以<code>符号引用</code>所表示的方法转换为实际方法的直接引用。</p>
<h3 id="什么是符号引用？"><a href="#什么是符号引用？" class="headerlink" title="什么是符号引用？"></a>什么是符号引用？</h3><p><img src="http://cdn.mjava.top/blog/20200731110742.png" alt></p>
<p>通过查看字节码，上面的<code>#7</code>，<code>#8</code>，<code>#9</code>等等都是符号引用，他在class文件里只是个符号，就像你定义一个变量名称一样，变量名只是和<code>字符符号</code>，并不是真正的指向内存的地址指针。这些符号都指向<code>运行时常量池</code>的引用。</p>
<h2 id="方法返回地址"><a href="#方法返回地址" class="headerlink" title="方法返回地址"></a>方法返回地址</h2><p>Java在调用方法时，只有两种返回方法，一种是<code>正常返回</code>，一种是<code>异常返回</code>。</p>
<h3 id="正常返回"><a href="#正常返回" class="headerlink" title="正常返回"></a>正常返回</h3><p>正常返回指的就是在执行方法时，中间并没有异常抛出，或者已正确处理抛出的异常，这时就称当前<code>方法正常调用完成</code>，如果有返回值，就会给他调用者返回一个值，如果没有返回值(<code>void</code>)就正常返回。</p>
<p>这种场景下，当前栈帧承担着恢复调用者状态的责任，<strong>包括恢复调用者的局部变量表和操作数栈，以及正确递增程序计数器，以跳过刚才执行的调用方法指令等。</strong>调用者的代码在被调用方法的返回值压入调用者栈帧的操作数栈后，会正常执行。</p>
<h3 id="异常返回"><a href="#异常返回" class="headerlink" title="异常返回"></a>异常返回</h3><p>在调用一些方法时，一些异常没有被正确捕获，就会导致方法终止，此时称<code>方法异常调用完成</code>，那一定不会有方法返回值返回给其调用者。</p>
<p>无论采用何种退出方式，在方法退出之后，都<strong>必须返回到最初方法被调用时的位置</strong>，程序才能继续执行，方法返回时可能需要在栈帧中保存一些信息，用来帮助恢复它的上层主调方法的执行状态。</p>
<p>怎么理解这个<strong>必须返回到最初方法被调用时的位置</strong>呢？</p>
<p>eg:</p>
<p><img src="http://cdn.mjava.top/blog/20200731164803.png" alt></p>
<p>上面异常是在<code>13行</code>发生的，但是它并没有停在<code>13行</code>，而是回到了最初调用它<code>第10行</code>的位置。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/java-class-load-2/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/java-class-load-2/" class="post-title-link" itemprop="url">JVM类加载过程</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:04:22" itemprop="dateCreated datePublished" datetime="2020-09-16T15:04:22+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="加载"><a href="#加载" class="headerlink" title="加载"></a>加载</h2><ol>
<li><p>通过一个类的全限定名(例如：<code>java.lang.String</code>)来获取定义此类的二进制字节流。</p>
</li>
<li><p>将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。</p>
</li>
<li><p>在内存中生成一个代表这个类的<code>java.lang.Class</code>对象，作为方法区这个类的各种数据的访问入口。</p>
</li>
</ol>
<blockquote>
<p>对于数组类而言，情况就有所不同，数组类本身不通过类加载器创建，它是由Java虚拟机直接在内存中动态构造出来的。</p>
</blockquote>
<ul>
<li><p>从ZIP压缩包中读取，这很常见，最终成为日后JAR、EAR、WAR格式的基础。</p>
</li>
<li><p>从网络中获取，这种场景最典型的应用就是Web Applet。</p>
</li>
<li><p>运行时计算生成，这种场景使用得最多的就是动态代理技术，在java.lang.reflect.Proxy中，就是用了ProxyGenerator.generateProxyClass()来为特定接口生成形式为“*$Proxy”的代理类的二进制字节流。</p>
</li>
<li><p>由其他文件生成，典型场景是JSP应用，由JSP文件生成对应的Class文件。</p>
</li>
<li><p>从数据库中读取，这种场景相对少见些，例如有些中间件服务器（如SAP Netweaver）可以选择把程序安装到数据库中来完成程序代码在集群间的分发。</p>
</li>
<li><p>可以从加密文件中获取，这是典型的防Class文件被反编译的保护措施，通过加载时解密Class文件来保障程序运行逻辑不被窥探。</p>
</li>
</ul>
<h2 id="验证"><a href="#验证" class="headerlink" title="验证"></a>验证</h2><ul>
<li>文件格式验证<ul>
<li>是否以魔数0xCAFEBABE开头。</li>
<li>主、次版本号是否在当前Java虚拟机接受范围之内</li>
<li>常量池的常量中是否有不被支持的常量类型（检查常量tag标志）。</li>
<li>指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。</li>
<li>CONSTANT_Utf8_info型的常量中是否有不符合UTF-8编码的数据。</li>
<li>·Class文件中各个部分及文件本身是否有被删除的或附加的其他信息</li>
<li>……</li>
</ul>
</li>
<li>元数据验证<ul>
<li>这个类是否有父类（除了java.lang.Object之外，所有的类都应当有父类）。</li>
<li>这个类的父类是否继承了不允许被继承的类（被final修饰的类）。</li>
<li>如果这个类不是抽象类，是否实现了其父类或接口之中要求实现的所有方法。</li>
<li>类中的字段、方法是否与父类产生矛盾（例如覆盖了父类的final字段，或者出现不符合规则的方法重载，例如方法参数都一致，但返回值类型却不同等）。</li>
<li>……</li>
</ul>
</li>
<li>字节码验证<ul>
<li>保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作，例如不会出现类似于“在操作栈放置了一个int类型的数据，使用时却按long类型来加载入本地变量表中”这样的情况。</li>
<li>保证任何跳转指令都不会跳转到方法体以外的字节码指令上。</li>
<li>保证方法体中的类型转换总是有效的，例如可以把一个子类对象赋值给父类数据类型，这是安全的，但是把父类对象赋值给子类数据类型，甚至把对象赋值给与它毫无继承关系、完全不相干的一个数据类型，则是危险和不合法的。</li>
<li>……</li>
</ul>
</li>
<li>符号引用验证<ul>
<li>符号引用中通过字符串描述的全限定名是否能找到对应的类</li>
<li>在指定类中是否存在符合方法的字段描述符及简单名称所描述的方法和字段。</li>
<li>符号引用中的类、字段、方法的可访问性（private、protected、public、<package>）是否可被当前类访问。</package></li>
<li>……</li>
</ul>
</li>
<li></li>
</ul>
<h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><p>准备阶段是正式为类中定义的变量（即静态变量，被static修饰的变量）分配内存并设置类变量初始值的阶段</p>
<p>例子：</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 变量value在准备阶段过后的初始值为0而不是123</span></span><br><span class="line"><span class="comment">// 因为这时尚未开始执行任何Java方法 value赋值为123的动作要到类的初始化阶段才会被执行</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> value = <span class="number">123</span></span><br></pre></td></tr></table></figure>

<p><img src="http://cdn.mjava.top/blog/20200726220517.jpeg" alt></p>
<h2 id="解析"><a href="#解析" class="headerlink" title="解析"></a>解析</h2><p>解析阶段是Java虚拟机将常量池内的<code>符号引用</code>替换为<code>直接引用</code>的过程</p>
<ul>
<li><p><strong>符号引用（Symbolic References）</strong>：符号引用以一组符号来描述所引用的目标，符号可以是任何形式的字面量，只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关，引用的目标并不一定是已经加载到虚拟机内存当中的内容。各种虚拟机实现的内存布局可以各不相同，但是它们能接受的符号引用必须都是一致的，因为符号引用的字面量形式明确定义在《Java虚拟机规范》的Class文件格式中。</p>
<blockquote>
<p>下面红框中的都属于符号引用</p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200726220833.png" alt></p>
</li>
<li><p><strong>直接引用（Direct References）</strong>：直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。直接引用是和虚拟机实现的内存布局直接相关的，同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用，那引用的目标必定已经在虚拟机的内存中存在。</p>
</li>
</ul>
<h2 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h2><p>参考：<a href="https://mp.weixin.qq.com/s?__biz=MzAxMTc4NDUyOA==&tempkey=MTA3MV9NS1dJTVFnVDhRQkRid2hBSDB4aUE2X3Nham5Lcm9VMlpXVlIzTGd4dkk0eDNNb29iV3NlaGh0blA3Z25CcmJ6cXBLYzl5Z09zakZSakNTeFdTOUtkbUQzZnNST0pnUUNTOEhkb1J3Ul84MDhPaEw1bGZSVm9TdXNteG5DLUowSDdmUGxYajkxSWFETENkZ0h0NTY1UkJfOC0yV0laXzdyakNfVDdnfn4%3D&chksm=03a1657734d6ec6126a1c6a802506964f632a2dff53f123de74de0f865b83ef11a9b338a187d#rd" rel="noopener external nofollow noreferrer" target="_blank">jvm类初始化</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://mjava.top/java/jvm/java-class-load-1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="灰灰">
      <meta itemprop="description" content="浅水是喧哗的，深水是沉默的">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="灰色World">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/java/jvm/java-class-load-1/" class="post-title-link" itemprop="url">JVM中的双亲委派机制</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-09-16 15:02:34" itemprop="dateCreated datePublished" datetime="2020-09-16T15:02:34+00:00">2020-09-16</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-01-27 10:07:24" itemprop="dateModified" datetime="2021-01-27T10:07:24+00:00">2021-01-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/JVM/" itemprop="url" rel="index"><span itemprop="name">JVM</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="四种类加载器"><a href="#四种类加载器" class="headerlink" title="四种类加载器"></a>四种类加载器</h2><ul>
<li>启动类加载器(Bootstrap Class Loader )：加载<code>$JAVA_HOME/jre/lib</code>目录下的jar包</li>
<li>拓展类加载器(Extension Class Loader)：加载<code>$JAVA_HOME/jre/lib/ext</code>目录下的jar包</li>
<li>应用程序类加载器(Application Class Loader)：加载<code>ClassPath</code>目录下的jar包</li>
<li>自定义类加载器(User Class Loader)：加载自定义指定目录下的jar包</li>
</ul>
<h2 id="双亲委派机制"><a href="#双亲委派机制" class="headerlink" title="双亲委派机制"></a>双亲委派机制</h2><blockquote>
<p> 如果一个类加载器收到了类加载的请求，它首先不会自己去尝试加载这个类，而是把这个请求委派给父类加载器去完成，每一个层次的类加载器都是如此，因此所有的加载请求最终都应该传送到最顶层的启动类加载器中，只有当父加载器反馈自己无法完成这个加载请求（它的搜索范围中没有找到所需的类）时，子加载器才会尝试自己去完成加载。</p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200726204658.jpg" alt></p>
<h2 id="代码示例"><a href="#代码示例" class="headerlink" title="代码示例"></a>代码示例</h2><blockquote>
<p>当获取<code>Bootstrap class loader</code>的时候，输出了<code>null</code>，说明<strong>开发者无法通过引用操作启动类加载器</strong></p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200726210142.png" alt></p>
<h2 id="双亲委派机制的作用"><a href="#双亲委派机制的作用" class="headerlink" title="双亲委派机制的作用"></a>双亲委派机制的作用</h2><p>每个加载器都只需要固定的加载自己管理范围内的类，这样的好处就是<code>保证了Java体系的稳定</code>，不然的话你自己定义一个<code>String</code>类的话，这样系统中就会有两个<code>String</code>类，如果没有双亲委派机制的话，系统就不知道到底该加载哪一个，这样系统就变得一片混乱了。</p>
<h2 id="破坏双亲委派机制"><a href="#破坏双亲委派机制" class="headerlink" title="破坏双亲委派机制"></a>破坏双亲委派机制</h2><p>双亲委派机制是Java设计者推荐给开发者们的类加载实现方式，并不是一个强制性约束的模型，所以也可以人为的破坏这个机制。</p>
<ul>
<li>源码</li>
</ul>
<blockquote>
<p>源码在<code>java.lang.ClassLoader</code>有兴趣的可以去看下</p>
</blockquote>
<p><img src="http://cdn.mjava.top/blog/20200726212038.png" alt></p>
<p>可以看到，就这短短的几行代码，就实现了听起来很高大上的<code>双亲委派机制</code>，所以破坏双亲委派机制的话，就直接重写<code>loadClass</code>方法就可以了。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><span class="space">&hellip;</span><a class="page-number" href="/page/6/">6</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">灰灰</p>
  <div class="site-description" itemprop="description">浅水是喧哗的，深水是沉默的</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">59</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">16</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">56</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/greycode9" title="GitHub → https://github.com/greycode9" rel="noopener external nofollow noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:zhengminghui99@gmail.com" title="E-Mail → mailto:zhengminghui99@gmail.com" rel="noopener external nofollow noreferrer" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      Links
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://www.yuque.com/huihui-r7gwx" title="https://www.yuque.com/huihui-r7gwx" rel="noopener external nofollow noreferrer" target="_blank">语雀</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        
  <div class="beian"><a href="https://beian.miit.gov.cn" rel="noopener external nofollow noreferrer" target="_blank">赣ICP备17003482号 </a>
  </div>

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">灰灰</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io" class="theme-link" rel="noopener external nofollow noreferrer" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org" class="theme-link" rel="noopener external nofollow noreferrer" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script><script src="/js/motion.js"></script>
<script src="/js/schemes/muse.js"></script>
<script src="/js/next-boot.js"></script>



  




  <script src="/js/local-search.js"></script>












  

  
      

<script>
  if (typeof MathJax === 'undefined') {
    window.MathJax = {
      loader: {
          load: ['[tex]/mhchem'],
        source: {
          '[tex]/amsCd': '[tex]/amscd',
          '[tex]/AMScd': '[tex]/amscd'
        }
      },
      tex: {
        inlineMath: {'[+]': [['$', '$']]},
          packages: {'[+]': ['mhchem']},
        tags: 'ams'
      },
      options: {
        renderActions: {
          findScript: [10, doc => {
            document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
              const display = !!node.type.match(/; *mode=display/);
              const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
              const text = document.createTextNode('');
              node.parentNode.replaceChild(text, node);
              math.start = {node: text, delim: '', n: 0};
              math.end = {node: text, delim: '', n: 0};
              doc.math.push(math);
            });
          }, '', false],
          insertedScript: [200, () => {
            document.querySelectorAll('mjx-container').forEach(node => {
              let target = node.parentNode;
              if (target.nodeName.toLowerCase() === 'li') {
                target.parentNode.classList.add('has-jax');
              }
            });
          }, '', false]
        }
      }
    };
    (function () {
      var script = document.createElement('script');
      script.src = '//cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
      script.defer = true;
      document.head.appendChild(script);
    })();
  } else {
    MathJax.startup.document.state(0);
    MathJax.texReset();
    MathJax.typeset();
  }
</script><!-- hexo-inject:begin --><!-- hexo-inject:end -->

    

  

</body>
</html>
